import datetime
import json
import random
import time

from Demos.win32ts_logoff_disconnected import username
from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import render
from fontTools.misc.textTools import tostr
from langchain.memory import ConversationBufferMemory
from langchain_community.llms.tongyi import Tongyi
from langchain_core.prompts import PromptTemplate
from rest_framework.response import Response
from rest_framework.views import APIView
from sympy import Q

from tools.Factory import sflogin
from tools.FileTools import FileLoaderFactory
from user.models import UserModel, Essay, Video, Dynamic
from user.ser import UserSer, EssaySer, VideoSer, DynamicSer
from user.models import UserModel
from user.ser import UserSer

import re

from utils.MyJWT import myjwt, MyJWT

import re

from utils.MyRedis import r
from utils.Mypaqu import run
from utils.Sendcode import SendCode
from utils.beidu import Baidu
from utils.myjwtt import mjwt


# Create your views here.
class LoginView(APIView):

    def post(self, request):
        # jwt工具包实例化

        # 账号
        account = request.data.get('phone')
        # 密码
        password = request.data.get('password')
        user = UserModel.objects.filter(phone=account, password=password).first()
        if user:
            return Response({"msg": "登录成功", "token": myjwt.getToken(user.id, user.phone),
                             "retoken": myjwt.regetToken(user.id, user.phone), "userid": user.id, "code": 200})
        else:
            return Response({"msg": "登录失败"})


class CaptchaAPIView(APIView):
    def get(self, request):
        # 手机号
        phone = request.query_params.get('phone')
        # re正则校验
        data = re.match(r'^1[3-9]\d{9}$', phone)
        if data:
            # 手机验证码实例化
            sendcode = SendCode()
            # Redis实例化
            # 随机生成验证码
            code = random.randint(1000, 9999)
            # 使用redis实例化中的方法将phone手机号作为键名code随机生成的验证码作为值设置有效时长60秒
            r.setex_str(phone, 60, code)
            # 得到结果看是否已经发送过去验证码
            type = sendcode.send_message(phone, code)
            if type:
                return Response({"code": 200, "captcha": code})
            else:
                return Response({"code": 400, "msg": "验证码发送失败"})
        else:
            return Response({"code": 400, "msg": "手机号格式不正确"})


# 验证码登录
class CaptLogin(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        captcha = request.data.get('captcha')
        # 正则验证
        res = re.match(r'^1[3-9]\d{9}$', phone)
        if res:
            # 假设验证码在Redis中的键是 phone:captcha，值是验证码的哈希值
            sss = r.get_str(phone)
            if sss == captcha:
                user = UserModel.objects.filter(phone=phone).first()
                if user:
                    ser = UserSer(user)
                    return Response(
                        {"msg": "登录成功", "userid": ser.data["id"], "token": myjwt.getToken(user.id, phone),
                         "retoken": myjwt.regetToken(user.id, phone), "code": 200})
                else:
                    ser = UserSer(data=request.data)
                    if ser.is_valid():
                        ser.save()
                        return Response({"msg": "登录成功", "userid": ser.data["id"],
                                         "token": myjwt.getToken(ser.data["id"], phone),
                                         "retoken": myjwt.regetToken(ser.data["id"], phone), "code": 200})
                    else:
                        return Response({"msg": ser.errors})
            else:
                return Response({"msg": "验证码失败"})
        else:
            return Response({"msg": "手机号格式错误"})


class DingTalkLogin(APIView):
    def get(self, request):
        types = request.query_params['types']
        fact = sflogin.create_factory(types)
        url = fact.geturl()
        return Response(url)


class DingTalkCallback(APIView):
    def get(self, request):
        types = request.query_params['types']
        fact = sflogin.create_factory(types)
        url = fact.callback(request)
        return HttpResponseRedirect(url)


# 退出登录
class quitView(APIView):
    def post(self, request):
        # 获取前端原始token
        token = request.headers.get('Authorization')
        # 将token进行切割
        mytoken = token.split(' ')[1]
        myjwt = MyJWT()
        # 解析切割后的token获取到token里带的用户信息和过期时间
        data = myjwt.Checktoken(mytoken)
        # 计算时间用仙子时间减去token过期时间得到还有多少秒token才会过期
        expiration = (int(data['exp']) - int(time.time()))
        # 存入redis中将原始token作为键expiration作为值和过期时间
        r.setex_str(token, expiration, expiration)
        return Response({"msg": "退出成功", "code": 200})


# 定时刷新token过期时间
class RefreshTokenView(APIView):
    def post(self, request):
        # 获取前端原始retoken
        try:
            retoken = request.data.get('retoken')
            # 将token进行切割
            myretoken = retoken.split(" ")[1]
            print(retoken)
            print(myretoken)
            myjwt = MyJWT()
            # 解析切割后的token获取到token里带的用户信息和过期时间
            data = myjwt.Checktoken(myretoken)
            print(data)
            if int(time.time()) >= int(data['exp']):
                return Response({"msg": "token过期了", "code": 400})
            else:
                return Response({"msg": "重新生成成功", 'code': 200, 'token': myjwt.getToken(data['id'], data['username']),
                                 "retoken": myjwt.regetToken(data['id'], data['username']), "userid": data['id']})
        except:
            return Response({'code':'400'})


# 链接百度接口
class BaiDuAPI(APIView):
    def post(self, request):
        id = request.data.get('id')
        url = request.data.get("url")
        # bdapi = Baidu()
        # data = bdapi.idcard(url)
        # 获取redis存储的用户信息
        redisvalue = r.get_str(url)
        # 获取到的用户信息转换成json格式数据
        data = json.loads(redisvalue.replace("'", '"'))
        ser = UserModel.objects.filter(id=id).first()
        print(ser.id)

        ser.Realname = data.get('name')
        ser.identity = data.get('code')
        ser.sex = data.get('sex')
        ser.save()
        return Response({"msg": "实名认证成功", "code": 200})


from qiniu import Auth


class QnToken(APIView):
    def get(self, request):
        # 需要填写你的 Access Key 和 Secret Key
        access_key = 'WLAlio0GglAMXyspzFORafAXys2TtW-rGw9BQ0id'
        secret_key = '5XmhE5n-sK_1yFPHNhqY_AaCCWaK-uqK6y5ZzXnn'
        # 构建鉴权对象
        q = Auth(access_key, secret_key)
        # 要上传的空间
        bucket_name = 'fjdi'

        # 3600为token过期时间，秒为单位。3600等于一小时
        token = q.upload_token(bucket_name)
        return Response({"code": 10000, 'data': token})


class UserView(APIView):
    def get(self, request):
        userid = request.query_params.get("userid")
        user = UserModel.objects.filter(id=userid).first()
        ser = UserSer(user)
        return Response({"code": 200, "data": ser.data})
    def put(self,request):
        user = UserModel.objects.get(id=request.data.get('id'))
        user.username=request.data.get('username')
        user.individual =request.data.get('individual')
        user.headimg = request.data.get('headimg')
        user.birthday = request.data.get('birthday')
        user.address = request.data.get('address')
        user.sex = request.data.get('sex')
        user.save()
        return Response({"code": 200,'msg':'修改成功'})



# 存入redis
class AddRedis(APIView):
    def get(self, request):
        url = request.query_params.get("url")
        r.list_push('beidulist', url)

        return Response({"code":200,"msg": "正在处理中"})


# 文章查询视图
class EssayfindView(APIView):
    def get(self, request):
        userid = request.query_params.get("userid")
        essay = Essay.objects.filter(user=userid)
        ser = EssaySer(essay, many=True)
        return Response({"code": 200, "data": ser.data})


# 视频查询视图
class VideofindView(APIView):
    def get(self, request):
        userid = request.query_params.get("userid")
        video = Video.objects.filter(user=userid).order_by('-addtime')
        ser = VideoSer(video, many=True)
        return Response({"code": 200, "data": ser.data})

# 动态查询视图
class DynamicfindView(APIView):
    def get(self, request):
        userid = request.query_params.get("userid")
        dynamic = Dynamic.objects.filter(user=userid)
        ser = DynamicSer(dynamic, many=True)
        for i in ser.data:
            i["imglist"]=i["imglist"].split(',')
        return Response({"code": 200, "data": ser.data})


# 最近发布视图
class UserRecentPublishView(APIView):
    def get(self, request):
        userid = request.query_params.get("userid")
        # 最近动态
        dynamic = Dynamic.objects.filter(user=userid)
        dynamic_ser = DynamicSer(dynamic, many=True)
        # 最近动态
        video = Video.objects.filter(user=userid)
        video_ser = VideoSer(video, many=True)
        # 最近文章
        essay = Essay.objects.filter(user=userid)
        essay_ser = EssaySer(essay, many=True)
        data = []
        for i in dynamic_ser.data:
            i["imglist"] = i["imglist"].split(',')

        for i in dynamic_ser.data:
            i['kind'] = 2
            data.append(i)
        for i in video_ser.data:
            i['kind'] = 1
            data.append(i)
        for i in essay_ser.data:
            i['kind'] = 0
            data.append(i)
        data.sort(key=lambda x: x['addtime'], reverse=True)
        return Response({"code": 200, 'data': data})


from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
import random


class TestWebsocket(APIView):
    def get(self, request):
        # 获取信息
        # 查询数据库对比

        # update = AllDataConsumersUpdate()
        # update.all_active_visit_data()
        channel_layer = get_channel_layer()
        send_data = {"error": "1号大鹏温度太高", 'namelist': ['1001', '1002'],
                     'valuelist': [random.randint(10, 100), random.randint(100, 200)]}
        # send_data = {"name":rand.randint(1,100)}
        async_to_sync(channel_layer.group_send)(
            '1',  # 房间组名
            {
                'type': 'send_to_chrome',  # 消费者中处理的函数
                'data': send_data
            }
        )
        return JsonResponse({"code": 200, "msg": "更新数据成功"})

class DataManage(APIView):
    def get(self,request):
        code = request.GET.get('code')
        number = random.randint(10, 100)
        # paramiko
        return Response({"code": 200, 'mes': {"code": code, "number": number}})


# 导入所需的模块和类
from langchain.embeddings import CacheBackedEmbeddings
from langchain.storage import LocalFileStore
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain.embeddings.dashscope import DashScopeEmbeddings

from langchain_text_splitters import CharacterTextSplitter
from utils.Mydb import db

# 向量数据库
class DatmManage(APIView):
    def post(self, request):
        url = request.data.get('url')
        file = FileLoaderFactory()
        file.load_to_vector_db("./upload/userheadimg/" + url)

        # data = []
        #
        # dynamic = Dynamic.objects.all()
        # dynamic_ser = DynamicSer(dynamic, many=True)
        # # 最近动态
        # video = Video.objects.all()
        # video_ser = VideoSer(video, many=True)
        # # 最近文章
        # essay = Essay.objects.all()
        # essay_ser = EssaySer(essay, many=True)
        # for i in dynamic_ser.data:
        #     i["imglist"] = i["imglist"].split(',')
        # for i in dynamic_ser.data:
        #     data.append(i)
        # for i in video_ser.data:
        #     data.append(i)
        # for i in essay_ser.data:
        #     data.append(i)
        # data.sort(key=lambda x: x['addtime'], reverse=True)
        # # print(data)
        # run()
        # with open('./utils/temp.txt',"a",encoding='utf-8') as f:
        #     for i in data:
        #         f.write(f"标题{i}+\n")

        doc = TextLoader('./utils/temp.txt', encoding='utf - 8').load()
        spliter = CharacterTextSplitter("\n", chunk_size=200, chunk_overlap=20)
        chunks = spliter.split_documents(doc)
        db.add(chunks, "doctors")

        return Response({"code": 200})


# 初始化 ConversationBufferMemory
memory = ConversationBufferMemory(return_messages=True)


def limit_conversation_to_last_three(memory):
    """
    此函数用于限制 ConversationBufferMemory 中的对话为最近的三轮
    :param memory: ConversationBufferMemory 实例
    :return: 无，直接修改传入的 memory 对象
    """
    messages = memory.chat_memory.messages
    # 计算消息总数
    total_messages = len(messages)
    if total_messages > 6:  # 因为一轮对话包含一个 HumanMessage 和一个 AIMessage，三轮就是6条消息
        # 截取最近的6条消息
        new_messages = messages[-6:]
        # 清空原有的消息
        memory.chat_memory.clear()
        # 添加最近的6条消息
        for message in new_messages:
            if "HumanMessage" in message.type:
                memory.chat_memory.add_user_message(message.content)
            elif "AIMessage" in message.type:
                memory.chat_memory.add_ai_message(message.content)


# 加载文档并将其拆分成片段
class DateManage(APIView):
    def post(self, request):
        ask = request.data['ask']
        key = 'doctors'
        res = db.search(ask, key, 3)

        # 将用户提问添加到记忆中
        memory.chat_memory.add_user_message(ask)

        # 获取历史对话
        history = ""
        messages = memory.chat_memory.messages
        for i in range(0, len(messages), 2):
            user_msg = messages[i].content if i < len(messages) else ""
            ai_msg = messages[i + 1].content if i + 1 < len(messages) else ""
            history += f"用户: {user_msg}\nAI: {ai_msg}\n"

        # 定义一个模板，将历史记录也包含进去
        pp = "以下是之前的对话历史：\n{history}\n问题是{ask}，答案是{answer},请只给我回答问题，不要分析"
        # 实例化模板类
        promptTemplate = PromptTemplate.from_template(pp)
        # 生成prompt
        prompt = promptTemplate.format(ask=ask, answer=res, history=history)

        # 实例化通义大模型
        tongyi = Tongyi()
        ret = tongyi.invoke(prompt)

        # 将AI回答添加到记忆中
        memory.chat_memory.add_ai_message(ret)

        # 限制对话历史为最近三轮
        limit_conversation_to_last_three(memory)

        return Response({"code": 200, "res": ret})

# 所有视频展示
class VideofindallView(APIView):
    def get(self, request):
        video = Video.objects.all().order_by('-addtime')
        ser = VideoSer(video, many=True)
        return Response({"code": 200, "data": ser.data})

# 接受文件
class FileView(APIView):
    def post(self, request):
        file = request.FILES['file']
        filename = file.name
        with open('./upload/userheadimg/' + filename, 'wb') as f:
            for f1 in file:
                f.write(f1)
        return Response("http://localhost:8000/upload/userheadimg/"+filename)

# 文章详情
class EssayfindOneView(APIView):
    def get(self, request):
        id = request.query_params.get('id')
        essay = Essay.objects.filter(id=id).first()
        ser = EssaySer(essay)
        data = ser.data
        data1 = []
        contlist = ser.data.get('content').split('#*#')
        imglist = ser.data.get('imglist').split(',')
        if (len(imglist) >= len(contlist)):
            for i in range(len(contlist)):
                data1.append({'ess': contlist[i], 'type': 0})
                data1.append({'ess': imglist[i], 'type': 1})
            if (len(imglist) > len(contlist)):
                for i in range(len(contlist), len(imglist)):
                    data1.append({'ess': imglist[i], 'type': 1})
        else:
            for i in range(len(imglist)):
                data1.append({'ess': contlist[i], 'type': 0})
                data1.append({'ess': imglist[i], 'type': 1})
            for i in range(len(imglist), len(contlist)):
                data1.append({'ess': contlist[i], 'type': 0})
        data['data'] = data1
        return Response({"code": 200, "data": data})
# 视频详情
class VideoFindByidView(APIView):
    def get(self,request):
        id = request.query_params.get("id")
        video = Video.objects.filter(id=id).first()
        ser = VideoSer(video)
        return Response({"code": 200, "data": ser.data})
